package dao

import (
	"fmt"
	"github.com/micro/go-micro/v2/errors"
	"golang.org/x/crypto/bcrypt"
	"gorm.io/gorm"
	"micro-grpc-server/services/user/internal/models"
	pb "micro-grpc-server/services/user/proto"
	wechat "micro-grpc-server/services/wechat/proto"
)

// 获取用户列表
func (d *UserDao) UserList(rq *pb.ListUserRequest) (list []*models.Identity, total int64, err error) {
	var query *gorm.DB
	// 查找指定用户表用户
	var identity = models.Identity{}
	query = d.Db.Model(identity)
	if len(rq.Scenario) > 0 {
		if !d.CheckScenario(rq.Scenario) {
			return nil, 0, errors.BadRequest(d.conf.ServerName, "请输入正确的Scenario")
		}
		tableName := d.getUserTableName(rq.Scenario)
		query = query.Joins(fmt.Sprintf("inner join %s on %s.`id` = %s.`id`", tableName, tableName, identity.TableName()))
	}

	// 获取total
	query.Count(&total)

	if rq.Page > 0 && rq.Limit > 0 {
		query.Limit(int(rq.Limit)).Offset(int(rq.Page-1) * int(rq.Limit))
	}

	if err := query.Find(&list).Error; err != nil {
		return list, total, err
	}
	return
}

// 普通注册
func (d *UserDao) RegisterNormal(rq *pb.RegisterRequest) (identity *models.Identity, err error) {
	identity = &models.Identity{
		Account: rq.Account,
		Phone:   rq.Phone,
		Name:    rq.Account,
	}
	password, err := bcrypt.GenerateFromPassword([]byte(rq.Password), bcrypt.DefaultCost)

	if err != nil {
		return nil, err
	}
	identity.Password = string(password)

	if err := d.Db.Save(identity).Error; err != nil {
		return nil, err
	}
	return identity, nil
}

// 微信注册
func (d *UserDao) RegisterWechat(rq *wechat.WechatUserInfoResponse) (identity *models.Identity, err error) {
	// 先通过unionId看有没有这个用户
	identity, err = d.FindUserByUnionId(rq.UnionId)
	// 没有找到 但是信息里有手机号码
	if identity == nil && len(rq.PhoneNumber) > 0 {
		identity, err = d.FindUserByPhone(rq.PhoneNumber)
	}
	// 如果不是未找到而是其他错误
	if err != gorm.ErrRecordNotFound {
		return nil, nil
	}
	// 没有通行证
	if identity == nil {
		identity = &models.Identity{
			UnionId:  rq.UnionId,
			Phone:    rq.PhoneNumber,
			Name:     rq.NickName,
			Avatar:   rq.AvatarURL,
			Gender:   int(rq.Gender),
			City:     fmt.Sprintf("%s/%s/%s", rq.Country, rq.Province, rq.City),
			Referral: rq.Referral,
		}

		if err = d.Db.Model(identity).Save(identity).Error; err != nil {
			return nil, err
		}
	}
	// 给通行证建立相应的用户表信息
	if err := d.Db.Table(d.getUserTableName(rq.Scenario)).Create(&models.User{
		Id:            identity.Id,
		Openid:        rq.OpenId,
		TimeJoin:      identity.TimeJoin,
		TimeSubscribe: identity.TimeJoin,
	}).Error; err != nil {
		return nil, err
	}

	return
}

// 通过账号获取用户
func (d *UserDao) FindUserByUserId(id int64) (identity *models.Identity, err error) {
	err = d.Db.Model(identity).Where("id = ?", id).First(&identity).Error
	if err != nil {
		return nil, errors.BadRequest(d.conf.ServerName, "用户不存在!")
	}
	return
}

// 通过账号获取用户
func (d *UserDao) FindUserByAccount(account string) (identity *models.Identity, err error) {
	err = d.Db.Model(identity).Where("account = ?", account).First(&identity).Error
	if err != nil {
		return nil, err
	}
	return
}

// 通过邮箱获取用户
func (d *UserDao) FindUserByPhone(phone string) (identity *models.Identity, err error) {
	err = d.Db.Model(identity).Where("phone = ?", phone).First(&identity).Error
	if err != nil {
		return nil, err
	}
	return
}

// 通过openid获取用户
func (d *UserDao) FindUserByOpenid(openid string, scenario string) (identity *models.Identity, err error) {
	var user = &models.User{}
	err = d.Db.Table(d.getUserTableName(scenario)).Where("openid = ?", openid).First(&user).Error
	if err != nil {
		return nil, err
	}

	return user.Identity, nil
}

// 通过unionId获取用户
func (d *UserDao) FindUserByUnionId(unionId string) (identity *models.Identity, err error) {
	err = d.Db.Model(identity).Where("unionid = ?", unionId).First(&identity).Error
	if err != nil {
		return nil, err
	}
	return
}

// 获取场景用户的表名
func (d *UserDao) getUserTableName(scenario string) string {
	return fmt.Sprintf("%s_user", scenario)
}
